import { Route } from '@/types';
import cache from '@/utils/cache';
import got from '@/utils/got';
import { load } from 'cheerio';
import { parseDate } from '@/utils/parse-date';
import InvalidParameterError from '@/errors/types/invalid-parameter';

const baseUrl = 'https://www.acfun.cn';
const categoryMap = {
    184: {
        title: '二次元画师',
        realmId: 'realmId=18' + '&realmId=14' + '&realmId=51',
    },
    110: {
        title: '综合',
        realmId: 'realmId=5' + '&realmId=22' + '&realmId=28' + '&realmId=3' + '&realmId=4',
    },
    73: {
        title: '生活情感',
        realmId: 'realmId=50' + '&realmId=25' + '&realmId=34' + '&realmId=7' + '&realmId=6' + '&realmId=17' + '&realmId=1' + '&realmId=2' + '&realmId=49',
    },
    164: {
        title: '游戏',
        realmId: 'realmId=8' + '&realmId=53' + '&realmId=52' + '&realmId=11' + '&realmId=43' + '&realmId=44' + '&realmId=45' + '&realmId=46' + '&realmId=47',
    },
    74: {
        title: '动漫文化',
        realmId: 'realmId=13' + '&realmId=31' + '&realmId=48',
    },
    75: {
        title: '漫画文学',
        realmId: 'realmId=15' + '&realmId=23' + '&realmId=16',
    },
};
const sortTypeEnum = new Set(['createTime', 'lastCommentTime', 'hotScore']);
const timeRangeEnum = new Set(['all', 'oneDay', 'threeDay', 'oneWeek', 'oneMonth']);

export const route: Route = {
    path: '/article/:categoryId/:sortType?/:timeRange?',
    categories: ['anime'],
    example: '/acfun/article/110',
    parameters: { categoryId: '分区 ID，见下表', sortType: '排序，见下表，默认为 `createTime`', timeRange: '时间范围，见下表，仅在排序是 `hotScore` 有效，默认为 `all`' },
    features: {
        requireConfig: false,
        requirePuppeteer: false,
        antiCrawler: false,
        supportBT: false,
        supportPodcast: false,
        supportScihub: false,
    },
    name: '文章',
    maintainers: ['TonyRL'],
    handler,
    description: `| 二次元画师 | 综合 | 生活情感 | 游戏 | 动漫文化 | 漫画文学 |
  | ---------- | ---- | -------- | ---- | -------- | -------- |
  | 184        | 110  | 73       | 164  | 74       | 75       |

  | 最新发表   | 最新动态        | 最热文章 |
  | ---------- | --------------- | -------- |
  | createTime | lastCommentTime | hotScore |

  | 时间不限 | 24 小时 | 三天     | 一周    | 一个月   |
  | -------- | ------- | -------- | ------- | -------- |
  | all      | oneDay  | threeDay | oneWeek | oneMonth |`,
};

async function handler(ctx) {
    const { categoryId, sortType = 'createTime', timeRange = 'all' } = ctx.req.param();
    if (!categoryMap[categoryId]) {
        throw new InvalidParameterError(`Invalid category Id: ${categoryId}`);
    }
    if (!sortTypeEnum.has(sortType)) {
        throw new InvalidParameterError(`Invalid sort type: ${sortType}`);
    }
    if (!timeRangeEnum.has(timeRange)) {
        throw new InvalidParameterError(`Invalid time range: ${timeRange}`);
    }

    const url = `${baseUrl}/v/list${categoryId}/index.htm`;
    const response = await got.post(
        `${baseUrl}/rest/pc-direct/article/feed` +
            '?cursor=first_page' +
            '&onlyOriginal=false' +
            '&limit=10' +
            `&sortType=${sortType}` +
            `&timeRange=${sortType === 'hotScore' ? timeRange : 'all'}` +
            `&${categoryMap[categoryId].realmId}`,
        {
            headers: {
                referer: url,
            },
        }
    );

    const list = response.data.data.map((item) => ({
        title: item.title,
        link: `${baseUrl}/a/ac${item.articleId}`,
        author: item.userName,
        pubDate: parseDate(item.createTime, 'x'),
        category: item.realmName,
    }));

    const items = await Promise.all(
        list.map((item) =>
            cache.tryGet(item.link, async () => {
                const response = await got(item.link, {
                    headers: {
                        referer: url,
                    },
                });
                const $ = load(response.data);
                const articleInfo = $('.main script')
                    .text()
                    .match(/window.articleInfo = (.*);\n\s*window.likeDomain/)[1];
                const data = JSON.parse(articleInfo);

                item.description = data.parts[0].content;
                if (data.tagList) {
                    item.category = [item.category, ...data.tagList.map((tag) => tag.name)];
                }

                return item;
            })
        )
    );

    return {
        title: categoryMap[categoryId].title,
        link: url,
        item: items,
    };
}
